/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package palitosocket;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author mayra
 * @author raiene
 * @author tatiane
 */

public class Main {

    //instancia um servidor de socket
    private ServerSocket socketServer;
    //guarda a qtde de jogadores
    private int quantidadeJogadores = 0;
    //lista de jogadores
    private List<Jogador> jogadores = new ArrayList<Jogador>();
    //Guarda a aposta da rodada atual
    private int apostaMesaAtual = 0;
    //objeto do tipo Jogador q guarda o vencedor da partida
    private Jogador vencedor;
    //objeto do tipo Jogador q guarda o vencedor da rodada
    private Jogador vencedorAtual;
    //lista de apostas
    private List<String> aposta = new ArrayList<String>();
    //boolean q diz se há um jogo em andamento ou não
    private boolean jogoAndamento = false;

    /**
     * @param args the command line arguments
     */

    //classe principal
    public static void main(String[] args) {
        Main aplicativo = new Main();

    }

    //metodo para adicionar jogador
    private void AdicionarJogador(Socket socket) {
        try {

            //instancia o jogador
            Jogador jogador = new Jogador();

            /**
             * cria variáveis de entrada e saída do tipo
             * de que permite entrada e saída pela rede
             */
            ObjectOutputStream saida = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream entrada = new ObjectInputStream(socket.getInputStream());

            //seta a entrada e a saída dos objetos
            jogador.setSaida(saida);
            jogador.setEntrada(entrada);
            //seta qual é a aposta na rodada
            jogador.setApostaMesaAtual(-1);

            /*
             *cria um dicionario de objetos do tipo string para entrada e saida
             *
             */
            HashMap<String, String> dadosEscrita = new HashMap<String, String>();
            HashMap<String, String> dadosLeitura = new HashMap<String, String>();

            //seta no dicionario com a chave estado string vazia
            dadosEscrita.put("estado", "");
            //seta no dicionario com a chave mensagem a mensagem
            dadosEscrita.put("mensagem", "Bem vindo(a) ao jogo do palito ");

            //pega a saída do objeto e escreve no dicionario de dados de escrita
            jogador.getSaida().writeObject(dadosEscrita);

            //limpa o objeto
            jogador.getSaida().flush();

            //le a entrada do objeto e chama método de leitura
            jogador.getEntrada().readObject();

            //adiciona o jogador na lista de jogadores
            jogadores.add(jogador);

        } catch (ClassNotFoundException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    //metodo que verifica se o jogador pertence ao jogo
   /* public boolean pertenceAoJogo(Jogador jogador) {

        for (Jogador j : jogadores) {
            if (jogador.equals(j)) {
                return true;
            }
        }
        return false;
    }*/

    /*
     * Verifica se algum jogador acertou
     * a aposta da mesa atual, caso
     * tenha acertado irá diminuir
     * um palito
     *
     * */
    private boolean checarAcertoJogado() {
        for (Jogador j : jogadores) {
            if (j.getApostaMesaAtual() == this.apostaMesaAtual) {
                j.tirarPalito();
                System.out.println("\n O jogador " + j.getNome() + " acertou, ele possui " + j.getPalitosTotal() + " palitos");
                vencedorAtual = j;
                return true;
            }

        }
        return false;

    }

    /*
     * Verifica se algum jogador não tem nenhum
     * palito, caso tenha irá terminar o jogo
     *
     * */
    private boolean verificarGanhador() {
        for (Jogador j : jogadores) {
            if (j.getPalitosTotal() == 0) {
                vencedor = j;
                return true;
            }
        }
        return false;

    }
    /*
     * Zera as apostas do jogadores
     * para a proxima rodada
     * */

    private void zerarApostas() {
        for (Jogador j : jogadores) {
            j.setApostaMesaAtual(-1);
        }

    }

    /*
     * pega as apostas de palitos
     *
     */
    private void apostaPalitos() throws IOException, ClassNotFoundException{
        
        HashMap<String, String> dadosSaida = new HashMap<String, String>();
        HashMap<String, String> dadosEntrada = new HashMap<String, String>();
        for (Jogador j : jogadores) {

            dadosSaida = new HashMap<String, String>();
            dadosSaida.put("mensagem", "O jogo começou");
            dadosSaida.put("estado", "jogando");
            dadosSaida.put("tipoAposta", "palito");

            /*
             * do while que verifica se o jagador esta colocando
             * na mesa uma quantidade de palito menor ou igual
             * ao valor que ele tem
             * */
            do {
                j.getSaida().writeObject(dadosSaida);
                j.getSaida().flush();
                System.out.println("palitos");
                dadosEntrada = (HashMap<String, String>) j.getEntrada().readObject();

                if (Integer.parseInt(dadosEntrada.get("apostaPalito")) > j.getPalitosTotal()) {
                    dadosSaida = new HashMap<String, String>();
                    dadosSaida.put("mensagem", "Você só tem " + j.getPalitosTotal() + " palito");
                    dadosSaida.put("estado", "jogando");
                    dadosSaida.put("tipoAposta", "palito");
                }

            } while (Integer.parseInt(dadosEntrada.get("apostaPalito")) > j.getPalitosTotal());

            System.out.println("Jogador " + dadosEntrada.get("nome") + " apostou " + dadosEntrada.get("apostaPalito"));
            j.setNome(dadosEntrada.get("nome"));
            j.setApostaPalitoAtual(Integer.parseInt(dadosEntrada.get("apostaPalito")));

            this.apostaMesaAtual = apostaMesaAtual + Integer.parseInt(dadosEntrada.get("apostaPalito"));
        }

        System.out.println("total palito: " + apostaMesaAtual);
    }

    /*
     * pega as apostas da mesa
     *
     */

    private void apostasMesa() throws IOException, ClassNotFoundException{
        HashMap<String, String> dadosSaida = new HashMap<String, String>();
        HashMap<String, String> dadosEntrada = new HashMap<String, String>();

        for (Jogador j : jogadores) {

            dadosSaida = new HashMap<String, String>();
            dadosSaida.put("mensagem", " ");
            dadosSaida.put("estado", "jogando");
            dadosSaida.put("tipoAposta", "mesa");

            /*
             * do while que verifica se a aposta ja existe
             * */
            do {
                j.getSaida().writeObject(dadosSaida);
                System.out.println("aposta");
                dadosEntrada = (HashMap<String, String>) j.getEntrada().readObject();

                /*
                 * for que pega as apostas dos jogadores e
                 * salva em uma lista
                 * */
                for (Jogador x : jogadores) {
                    aposta.add(String.valueOf(x.getApostaMesaAtual()));
                }
                /*
                 *verifica se aposta do jogador já existe
                 *
                 */
                if (aposta.contains(dadosEntrada.get("apostaMesa"))) {
                    dadosSaida = new HashMap<String, String>();
                    dadosSaida.put("mensagem", "Já existe essa aposta");
                    dadosSaida.put("estado", "jogando");
                    dadosSaida.put("tipoAposta", "mesa");                    
                }
                //repita enquanto houver entrada de apostas
            } while (aposta.contains(dadosEntrada.get("apostaMesa")));
            //limpa todas as apostas da rodada
            aposta.removeAll(aposta);

            System.out.println("Jogador " + dadosEntrada.get("nome") + " apostou na mesa " + dadosEntrada.get("apostaMesa"));
            j.setNome(dadosEntrada.get("nome"));
            j.setApostaMesaAtual(Integer.parseInt(dadosEntrada.get("apostaMesa")));
            /*
             * for que envia uma mensagem para todos os jogadores
             * avisando o valor das aposta
             * */
            for (Jogador y : jogadores) {

                System.out.println(y.getNome());
                dadosSaida = new HashMap<String, String>();
                dadosSaida.put("mensagem", j.getNome() + " apostou " + j.getApostaMesaAtual());
                dadosSaida.put("estado", " ");
                dadosSaida.put("tipoAposta", "resultado");
                y.getSaida().writeObject(dadosSaida);
                y.getSaida().flush();
                dadosEntrada = (HashMap<String, String>) y.getEntrada().readObject();
            }
        }

        dadosSaida = new HashMap<String, String>();
        dadosSaida.put("estado", "jogando");
    }
    public Main() {
        try {
            //instancia um objeto do tipo servidor socket na porta 2222
            socketServer = new ServerSocket(2222);
            HashMap<String, String> dadosSaida = new HashMap<String, String>();
            HashMap<String, String> dadosEntrada = new HashMap<String, String>();
            //enquanto o servidor estiver rodando...
            while (true) {
                //se o jogo não estiver em andamento
                if (!jogoAndamento) {
                System.out.println("aguardando jogador");
                //instancia um objeto socket para aceitar conexao do cliente
                Socket socket = socketServer.accept();
                //chama metodo e adiciona o cliente aceito pelo socket
                AdicionarJogador(socket);
                System.out.println("primeiro jogador");
                quantidadeJogadores++;
                }
                if (quantidadeJogadores == 1){
                    dadosSaida = new HashMap<String, String>();
                    dadosSaida.put("mensagem", "Você é o único no jogo. Aguarde mais jogadores.");

                }
                else {
                        //zera a rodada
                        apostaMesaAtual = 0;

                        //instancia um objeto jogador pra salvar o vencedor
                        this.vencedorAtual = new Jogador();
                        //mapeia os dados de entrada e saída
                        dadosSaida = new HashMap<String, String>();
                        
                        //chama metodo para iniciar apostas
                        apostaPalitos();

                        /*
                         * pega as apostas da mesa
                         * */
                         apostasMesa();
                        
                        String resultado = "Quantidade de palitos na mesa: " + this.apostaMesaAtual;
                        //se o retorno de checarAcertoJogado for true
                        if (this.checarAcertoJogado()) {
                            //concatena em resultado o nome do jogador que acertou
                            resultado = resultado + "\nO Jogador " + vencedorAtual.getNome() + " acertou!";
                        } else {
                            //concatena em resultado a mensagem que ninguem acertou
                            resultado = resultado + "\nNinguem acertou";
                        }
                        //se o houver vencedor
                        if (verificarGanhador()) {
                            //concatena em resultado o nome do jogador que venceu
                            resultado = resultado + "\nO jogador " + this.vencedor.getNome() + " ganhou ";
                            //seta para jogo parado
                            //jogoAndamento = false;
                            dadosSaida.put("", resultado);
                        }
                        else {
                            jogoAndamento = true;
                        }

                        dadosSaida.put("mensagem", resultado);

                        /*
                         * mostra o resultado para todos os jogadores
                         * na mesa 
                         * */

                        for (Jogador j : jogadores) {
                            
                            dadosSaida.put("tipoAposta", "resultado");
                            j.getSaida().writeObject(dadosSaida);
                            System.out.println("resultado");
                            dadosEntrada = (HashMap<String, String>) j.getEntrada().readObject();
                        }

                        /*
                         * limpa as aposta
                         * */
                        this.zerarApostas();
                        //break;
                    }


                //}//end switch
            }//while
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }//Main
}

